package com.wufeng.design.pattern;

public class Singleton {
    public static void main(String[] args) {
        Singleton01 singleton1 = Singleton01.getInstance();
        Singleton01 singleton2 = Singleton01.getInstance();
        System.out.println(singleton1 == singleton2);
        System.out.println(singleton1.hashCode());
        System.out.println(singleton2.hashCode());
        System.out.println(String.valueOf(1234).length() % 2 == 0);

    }
}

/**
 * 饿汉式(静态常量)
 * 类装载的时候就完成实例化，避免了线程的同步问题，没有达到Lazy Loading的效果。
 * 如果从始至终没有使用这个实例，则会造成内存的浪费。
 */
class Singleton01 {
    // 1、构造器私有化，外部不能new
    private Singleton01() {
    }

    // 2、本类内部创建对象实例
    private static final Singleton01 instance = new Singleton01();

    // 3、提供一个共有的静态方法，返回实例对象
    public static Singleton01 getInstance() {
        return instance;
    }
}

/**
 * 饿汉式(静态代码块创建)
 * 类装载的时候就执行静态块代码，初始化类的实例
 */
class Singleton02 {
    // 1、构造器私有化，外部不能new
    private Singleton02() {
    }

    // 2、本类内部创建对象实例
    private static final Singleton02 instance;

    static {
        instance = new Singleton02();
    }

    // 3、提供一个共有的静态方法，返回实例对象
    public static Singleton02 getInstance() {
        return instance;
    }
}

/**
 * 懒汉式（线程不安全的）
 * 起到了Lazy Loading的效果，线程不安全
 * 当一个线程走到了判断 if (instance == null)，未来得及执行下面的代码，
 * 另一个线程也通过了判断，这样会创建多个实例对象
 * <p>
 * 实际开发不用
 */
class Singleton03 {
    // 1、构造器私有化，外部不能new
    private Singleton03() {
    }

    // 2、本类内部创建对象实例
    private static Singleton03 instance;

    // 3、提供一个共有的静态方法,当被调用的时候才会创建单例对象，饿汉式
    public static Singleton03 getInstance() {
        if (instance == null) {
            instance = new Singleton03();
        }
        return instance;
    }
}

/**
 * 懒汉式（线程安全）
 * 给方法直接加 synchronized 加锁，但是效率低，不推荐
 * 同步代码块，没有线程安全问题，不能用
 * synchronized (Singleton04.class) {
 *                 instance = new Singleton04();
 *             }
 *
 */
class Singleton04 {
    // 1、构造器私有化，外部不能new
    private Singleton04() {
    }

    // 2、本类内部创建对象实例
    private static Singleton04 instance;

    // 3、提供一个共有的静态方法,当被调用的时候才会创建单例对象，饿汉式
    public static Singleton04 getInstance() {
        if (instance == null) {
            synchronized (Singleton04.class) {
                instance = new Singleton04();
            }
        }
        return instance;
    }
}

/**
 * DoubleCheck
 */
class Singleton05 {
    // 1、构造器私有化，外部不能new
    private Singleton05() {
    }
    // 2、本类内部创建对象实例 volatile 保证多线程的可见性
    private static volatile Singleton05 instance;

    // 3、提供一个共有的静态方法,当被调用的时候才会创建单例对象
    // 加入双重检查代码，确保线程安全，同时解决懒加载问题。 推荐使用
    public static Singleton05 getInstance() {
        if (instance == null) {
            synchronized (Singleton05.class) {
                if(instance == null){
                    instance = new Singleton05();
                }
            }
        }
        return instance;
    }
}